package com.leyou.job.lock.impl;

import com.leyou.job.lock.RedisLock;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Redis分布式锁
 */
public class SimpleRedisLock implements RedisLock {

    // 操作redis的模板
    private StringRedisTemplate redisTemplate;
    // 锁的名称
    private String key;
    // 锁对应的值：一个标记
    //private static final String value = "1";  // 版本1：是把标记写死的，这里有可能删除的是别人的锁

    // 给value一个唯一标识
    private final static String VALUE_PREFIX = UUID.randomUUID().toString();

    /**
     * 要想用这个锁，必须传入两个参数
     * @param redisTemplate     redis模板
     * @param key               锁的名称
     */
    public SimpleRedisLock(StringRedisTemplate redisTemplate, String key) {
        this.redisTemplate = redisTemplate;
        this.key = key;
    }

    /**
     * @param releaseTime   占用锁的时间 :单位是秒
     * @return
     */
    @Override
    public boolean lock(long releaseTime) {
        // 版本2： 给value赋予唯一标识
        String value = VALUE_PREFIX + Thread.currentThread().getId();

        /**
         * setIfAbsent：  如果redis中没有存在这个key，那么就可以插入；如果存在就插入不了
         */
        Boolean bool = redisTemplate.opsForValue().setIfAbsent(key, value, releaseTime, TimeUnit.SECONDS);
        return bool!=null && bool;
    }

    /**
     * 释放锁
     */
    @Override
    public void unlock() {
        // 锁对应的值
        String value = VALUE_PREFIX + Thread.currentThread().getId();
        // 判断是否是同一把锁
        String redisValue = redisTemplate.opsForValue().get(key);
        // 如果是同一把锁，才去删除
        if(StringUtils.equals(value, redisValue)){
            redisTemplate.delete(key);
        }
    }
}
